/*
 * generate_main.cpp
 *
 *  Created on: Apr 30, 2011
 *      Author: tqlong
 */

#include <boost/program_options.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <armadillo>
#include "common/common.h"

namespace po = boost::program_options;
po::options_description desc("Allowed options");
po::variables_map vm;

void process_options(int argc, char**  argv);
int doJob();

int main(int argc, char** argv)
{
	process_options(argc, argv);
	if (vm.count("help") || !vm.count("data"))
	{
		std::cout << desc << "\n";
		return 0;
	}
	boost::posix_time::ptime time_start(
	    boost::posix_time::microsec_clock::local_time());

	int retval = doJob();

	boost::posix_time::ptime time_end(
	    boost::posix_time::microsec_clock::local_time());
	boost::posix_time::time_duration duration(time_end - time_start);
	std::cerr << "Duration = " << duration << "\n";
	return retval;
}

void process_options(int argc, char** argv)
{
	desc.add_options()("help", "produce this usage")("data", po::value<
	    std::string>(), "file contains training samples")("noseed",
	    "do not generate random seed")("n",
	    po::value<long long>()->default_value(100), "number of points")("d",
	    po::value<int>()->default_value(2), "input dimension")("format",
	    po::value<std::string>()->default_value("txt"),
	    "data format: txt, bin, raw");
	po::store(po::parse_command_line(argc, argv, desc), vm);
	po::notify(vm);
}

int doJob()
{
	std::string format = vm["format"].as<std::string> ();
	std::string fName = vm["data"].as<std::string> ();
	long long n = vm["n"].as<long long> ();
	long long d = vm["d"].as<int> ();
	if (!vm.count("noseed"))
	{
		::srand(time(NULL));
	}

	std::ofstream os(fName.c_str());
	const char *type[3] = { "bin", "txt", "raw" };
	if (format == "bin")
	{
		std::cout << "binary format\n";
		os.write(type[0], 3);
		binary_write(os, n);
		binary_write(os, d);
	}
	else if (format == "txt")
	{
		std::cout << "text format\n";
		os.write(type[1], 3);
		os << n << " " << d << std::endl; // first line is information about data
	}
	else if (format == "raw")
	{
		std::cout << "raw format\n";
		os.write(type[2], 3);
		binary_write(os, n);
		binary_write(os, d);
	}

	arma::vec offset = arma::randn<arma::vec>(d) * 3;
	for (long long i = 0; i < n; i++)
	{
		arma::vec v = arma::randn<arma::vec>(d) * 5;
		v -= offset;
		if (format == "bin")
			v.save(os, arma::arma_binary);
		else if (format == "txt")
			v.save(os, arma::arma_ascii);
		else if (format == "raw")
			os.write((char*)v.memptr(), d*sizeof(double));
	}
	os.close();
	return 0;
}
